home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH20 / TRACEKBD.ASM < prev   
Encoding:
Assembly Source File  |  1994-07-24  |  6.9 KB  |  314 lines

  1.         .xlist
  2.         include     stdlib.a
  3.         includelib    stdlib.lib
  4.         .list
  5.  
  6. cseg        segment    para public 'code'
  7.         assume    ds:nothing
  8.  
  9. ; ScanCode must be in the Code segment.
  10.  
  11. ScanCode    db    0
  12.  
  13.  
  14.  
  15. ;****************************************************************************
  16. ;
  17. ; KbdSim- Passes the scan code in AL through the keyboard controller
  18. ; using the trace flag.  The way this works is to turn on the
  19. ; trace bit in the flags register.  Each instruction then causes a trace
  20. ; trap.  The (installed) trace handler then looks at each instruction to
  21. ; handle IN, OUT, INT, and other special instructions.  Upon encountering
  22. ; an IN AL, 60 (or equivalent) this code simulates the instruction and
  23. ; returns the specified scan code rather than actually executing the IN
  24. ; instruction.  Other instructions need special treatment as well.  See
  25. ; the code for details.  This code is pretty good at simulating the hardware,
  26. ; but it runs fairly slow and has a few compatibility problems.
  27.  
  28.  
  29. KbdSim        proc    near
  30.  
  31.         pushf
  32.         push    es
  33.         push    ax
  34.         push    bx
  35.  
  36.  
  37.         xor    bx, bx            ;Point es at int vector tbl
  38.         mov    es, bx            ; (to simulate INT 9).
  39.         cli                ;No interrupts for now.
  40.         mov    cs:ScanCode, al        ;Save output scan code.
  41.  
  42.         push    es:[1*4]        ;Save current INT 1 vector
  43.         push    es:2[1*4]        ; so we can restore it later.
  44.  
  45.  
  46.  
  47. ; Point the INT 1 vector at our INT 1 handler:
  48.  
  49.         mov    word ptr es:[1*4], offset MyInt1
  50.         mov    word ptr es:[1*4 + 2], cs
  51.  
  52.  
  53.  
  54. ; Turn on the trace trap:
  55.  
  56.         pushf
  57.         pop    ax
  58.         or    ah, 1
  59.         push    ax
  60.         popf
  61.  
  62.  
  63. ; Simulate an INT 9 instruction.  Note: cannot actually execute INT 9 here
  64. ; since INT instructions turn off the trace operation.
  65.  
  66.  
  67.         pushf
  68.         call    dword ptr es:[9*4]
  69.  
  70.  
  71. ; Turn off the trace operation:
  72.  
  73.  
  74.         pushf
  75.         pop    ax
  76.         and    ah, 0feh        ;Clear trace bit.
  77.         push    ax
  78.         popf
  79.  
  80.  
  81. ; Disable trace operation.
  82.  
  83.  
  84.         pop    es:[1*4 + 2]        ;Restore previous INT 1
  85.         pop    es:[1*4]        ; handler.
  86.  
  87.  
  88. ; Okay, we're done.  Restore registers and return.
  89.  
  90. VMDone:        pop    bx
  91.         pop    ax
  92.         pop    es
  93.         popf
  94.         ret
  95. KbdSim        endp
  96.  
  97.  
  98.  
  99. ;----------------------------------------------------------------------------
  100. ;
  101. ; MyInt1- Handles the trace trap (INT 1).  This code looks at the next
  102. ; opcode to determine if it is one of the special opcodes we have to
  103. ; handle ourselves.
  104.  
  105.  
  106. MyInt1        proc    far
  107.         push    bp
  108.         mov    bp, sp        ;Gain access to return adrs via BP.
  109.         push    bx
  110.         push    ds
  111.  
  112. ; If we get down here, it's because this trace trap is directly due to
  113. ; our having punched the trace bit.  Let's process the trace trap to
  114. ; simulate the 80x86 instruction set.
  115. ;
  116. ; Get the return address into DS:BX
  117.  
  118. NextInstr:    lds    bx, 2[bp]
  119.  
  120. ; The following is a special case to quickly eliminate most opcodes and
  121. ; speed up this code by a tiny amount.
  122.  
  123.         cmp    byte ptr [bx], 0cdh    ;Most opcodes are less than
  124.         jnb    NotSimpleInstr        ; 0cdh, hence we quickly
  125.         pop    ds            ; return back to the real
  126.         pop    bx            ; program.
  127.         pop    bp
  128.         iret
  129.  
  130. NotSimpleInstr:    je    IsIntInstr    ;If it's an INT instruction.
  131.  
  132.         mov    bx, [bx]    ;Get current instruction's opcode.
  133.         cmp    bl, 0e8h    ;CALL opcode
  134.         je    ExecInstr
  135.         jb    TryInOut0
  136.  
  137.         cmp    bl, 0ech    ;IN al, dx instr.
  138.         je    MayBeIn60
  139.         cmp    bl, 0eeh    ;OUT dx, al instr.
  140.         je    MayBeOut20
  141.         pop    ds        ;A normal instruction if we get
  142.         pop    bx        ; down here.
  143.         pop    bp
  144.         iret
  145.  
  146. TryInOut0:    cmp    bx, 60e4h    ;IN al, 60h instr.
  147.         je    IsINAL60
  148.         cmp    bx, 20e6h    ;out 20, al instr.
  149.         je    IsOut20
  150.  
  151. ; If it wasn't one of our magic instructions, execute it and continue.
  152.  
  153. ExecInstr:    pop    ds
  154.         pop    bx
  155.         pop    bp
  156.         iret
  157.  
  158. ; If this instruction is IN AL, DX we have to look at the value in DX to
  159. ; determine if it's really an IN AL, 60h instruction.
  160.  
  161. MayBeIn60:    cmp    dx, 60h
  162.         jne    ExecInstr
  163.         inc    word ptr 2[bp]        ;Skip over this 1 byte instr.
  164.         mov    al, cs:ScanCode
  165.         jmp    NextInstr
  166.  
  167. ; If this is an IN AL, 60h instruction, simulate it by loading the current
  168. ; scan code into AL.
  169.  
  170. IsInAL60:    mov    al, cs:ScanCode
  171.         add    word ptr 2[bp], 2    ;Skip over this 2-byte instr.
  172.         jmp     NextInstr
  173.  
  174.  
  175. ; If this instruction is OUT DX, AL we have to look at DX to see if we're
  176. ; outputting to location 20h (8259).
  177.  
  178. MayBeOut20:    cmp    dx, 20h
  179.         jne    ExecInstr
  180.         inc    word ptr 2[bp]        ;Skip this 1 byte instruction.
  181.         jmp    NextInstr
  182.  
  183. ; If this is an OUT 20h, al instruction, simply skip over it.
  184.  
  185. IsOut20:    add    word ptr 2[bp], 2    ;Skip instruction.
  186.         jmp    NextInstr
  187.  
  188.  
  189. ; IsIntInstr- Execute this code if it's an INT instruction.
  190. ;
  191. ; The problem with the INT instructions is that they reset the trace bit
  192. ; upon execution.  For certain guys (see above) we can't have that.
  193. ;
  194. ; Note: at this point the stack looks like the following:
  195. ;
  196. ;    flags
  197. ;
  198. ;    rtn cs -+
  199. ;        |
  200. ;    rtn ip    +-- Points at next instr the CPU will execute.
  201. ;    bp
  202. ;    bx
  203. ;    ds
  204. ;
  205. ; We need to simulate the appropriate INT instruction by:
  206. ;
  207. ;    (1) adding two to the return address on the stack (so it returns
  208. ;        beyond the INT instruction.
  209. ;    (2) pushing the flags onto the stack.
  210. ;    (3) pushing a phony return address onto the stack which simulates
  211. ;        the INT 1 interrupt return address but which "returns" us to
  212. ;        the specified interrupt vector handler.
  213. ;
  214. ; All this results in a stack which looks like the following:
  215. ;
  216. ;    flags
  217. ;
  218. ;    rtn cs -+
  219. ;        |
  220. ;    rtn ip    +-- Points at next instr beyond the INT instruction.
  221. ;
  222. ;    flags    --  Bogus flags to simulate those pushed by INT instr.
  223. ;
  224. ;    rtn cs -+
  225. ;        |
  226. ;    rtn ip  +-- "Return address" which points at the ISR for this INT instr.
  227. ;    bp
  228. ;    bx
  229. ;    ds
  230.  
  231.  
  232. IsINTInstr:     add    word ptr 2[bp], 2    ;Bump rtn adrs beyond INT instr.
  233.         mov    bl, 1[bx]
  234.         mov    bh, 0
  235.         shl    bx, 1            ;Multiply by 4 to get vector
  236.         shl    bx, 1            ; address.
  237.  
  238.         push    [bp-0]            ;Get and save BP
  239.         push    [bp-2]            ;Get and save BX.
  240.         push    [bp-4]            ;Get and save DS.
  241.  
  242.         push    cx
  243.         xor    cx, cx            ;Point DS at interrupt
  244.         mov    ds, cx            ; vector table.
  245.  
  246.         mov    cx, [bp+6]        ;Get original flags.
  247.         mov    [bp-0], cx        ;Save as pushed flags.
  248.  
  249.         mov    cx, ds:2[bx]        ;Get vector and use it as
  250.         mov    [bp-2], cx        ; the return address.
  251.         mov    cx, ds:[bx]
  252.         mov    [bp-4], cx
  253.  
  254.         pop    cx
  255.         pop    ds
  256.         pop    bx
  257.         pop    bp
  258.         iret
  259. ;
  260. MyInt1        endp
  261.  
  262.  
  263.  
  264.  
  265. ; Main program - Simulates some keystrokes to demo the above code.
  266.  
  267. Main        proc
  268.  
  269.         mov    ax, cseg
  270.         mov    ds, ax
  271.  
  272.         print
  273.         byte    "Simulating keystrokes via Trace Flag",cr,lf
  274.         byte    "This program places 'DIR' in the keyboard buffer"
  275.         byte    cr,lf,0
  276.  
  277.         mov    al, 20h            ;"D" down scan code
  278.         call    KbdSim
  279.         mov    al, 0a0h        ;"D" up scan code
  280.         call    KbdSim
  281.  
  282.         mov    al, 17h            ;"I" down scan code
  283.         call    KbdSim
  284.         mov    al, 97h            ;"I" up scan code
  285.         call    KbdSim
  286.  
  287.         mov    al, 13h            ;"R" down scan code
  288.         call    KbdSim
  289.         mov    al, 93h            ;"R" up scan code
  290.         call    KbdSim
  291.  
  292.         mov    al, 1Ch            ;Enter down scan code
  293.         call    KbdSim
  294.         mov    al, 9Ch            ;Enter up scan code
  295.         call    KbdSim
  296.  
  297.  
  298.  
  299.         ExitPgm
  300. Main        endp
  301.  
  302.  
  303. cseg        ends
  304.  
  305. sseg        segment    para stack 'stack'
  306. stk        db    1024 dup ("stack   ")
  307. sseg        ends
  308.  
  309. zzzzzzseg    segment    para public 'zzzzzz'
  310. LastBytes    db    16 dup (?)
  311. zzzzzzseg    ends
  312.         end    Main
  313.  
  314.